#include "node_spritenode.h"
#include "xfloathelper.h"
#include "g_graphics.h"
#include "xge.h"


namespace xge{
namespace graphics{

  void SpriteNode::UpdateQuadStatus() {
    // update the status of this quad
    float x1 , x2 , y1 , y2 ;
    float sinv , cosv ;
    x1 = -anchor().x() * scale().x();
    y1 = -anchor().y() * scale().y();
    x2 = (texture_rect().width() - anchor().x())* scale().x();
    y2 = (texture_rect().height() - anchor().y())* scale().y();
    if( FLOAT_ZERO( rotation() ) ) {
      sinv = sin(rotation());
      cosv = cos(rotation());
      quad_.vertex[0].x  = x1*cosv - y1*sinv + position().x();
      quad_.vertex[0].y  = x1*sinv + y1*cosv + position().y();	
      quad_.vertex[1].x  = x2*cosv - y1*sinv + position().x();
      quad_.vertex[1].y  = x2*sinv + y1*cosv + position().y();	
      quad_.vertex[2].x  = x2*cosv - y2*sinv + position().x();
      quad_.vertex[2].y  = x2*sinv + y2*cosv + position().y();	
      quad_.vertex[3].x  = x1*cosv - y2*sinv + position().x();
      quad_.vertex[3].y  = x1*sinv + y2*cosv + position().y();	
    } else {
      quad_.vertex[0].x = x1 + position().x(); 
      quad_.vertex[0].y = y1 + position().y();
      quad_.vertex[1].x = x2 + position().x(); 
      quad_.vertex[1].y = y1 + position().y();
      quad_.vertex[2].x = x2 + position().x(); 
      quad_.vertex[2].y = y2 + position().y();
      quad_.vertex[3].x = x1 + position().x(); 
      quad_.vertex[3].y = y2 + position().y();
    }

  }


  SpriteNode::SpriteNode(const TexturePtr& texture , const Rect & texture_rect , const Point& anchor_point , 
    const Point& hv_scale , const Point& position , float rotation , float zbuf , int blending ) 
    : ListBaseNode(texture,texture_rect,anchor_point,hv_scale,position,rotation) {
      set_color( Color::kBlack );
      set_blending( blending );
      set_z( zbuf );
  }


  void SpriteNode::OnPaint( const Timer::tick_t& diff_time ) {
    // first call the base on paint function to rendering the child node 
    ListBaseNode::OnPaint(diff_time);
    PaintSpriteOnly( diff_time );
  }

  void SpriteNode::PaintSpriteOnly( const Timer::tick_t& diff_time ) {
    // doing the on paint iteration here
    this->VisitAnimator(this,diff_time);
    // now update the internal data-structure
    this->UpdateQuadStatus();
    // rendering the quad
    XGameEngine::GetGraphics2D()->RenderQuad(quad_);
  }

  void SpriteNode::set_texture( const TexturePtr& t ) {
    if( texture().Get() == t.Get() )
      return;
    // adjusting the texture position here
    float w = (float)(t->width());
    float h = (float)(t->height());
    float tx1 , ty1 , tx2, ty2;
    if( !t.Null() ) {
      tx1 = texture_rect().left_up_point().x() / w;
      ty1 = texture_rect().left_up_point().y() / h;
      tx2 = (texture_rect().left_up_point().x()+ texture_rect().width()) / w ;
      ty2 = (texture_rect().left_up_point().y()+ texture_rect().height()) / h ;
    } else {
      tx1 = 0.0f;
      ty1 = 0.0f;
      tx2 = 1.0f;
      ty2 = 1.0f;
    }
    quad_.vertex[0].tx = tx1 ;
    quad_.vertex[0].ty = ty1 ;
    quad_.vertex[1].tx = tx2 ;
    quad_.vertex[1].ty = ty1 ;
    quad_.vertex[2].tx = tx2 ;
    quad_.vertex[2].ty = ty2 ;
    quad_.vertex[3].tx = tx1 ;
    quad_.vertex[3].ty = ty2 ;
    // set the texture real 
    ListBaseNode::set_texture( t );
  }

  void SpriteNode::set_texture_rect( const Rect& rect ) {
    if( rect == texture_rect() )
      return ;
    float x1,y1,x2,y2;
    if( texture().Null() ) {
      x1= rect.left_up_point().x();
      y1= rect.left_up_point().y();
      x2= rect.left_up_point().x()+rect.width();
      y2= rect.left_up_point().y()+rect.height();

    } else {
      float w = (float)(texture()->width());
      float h = (float)(texture()->height());
      x1= rect.left_up_point().x()/w;
      y1= rect.left_up_point().y()/h;
      x2= (rect.left_up_point().x()+rect.width())/w;
      y2= (rect.left_up_point().x()+rect.width())/h;
    }
    quad_.vertex[0].tx = x1 ;
    quad_.vertex[0].ty = y1 ;
    quad_.vertex[1].tx = x2 ;
    quad_.vertex[1].ty = y1 ;
    quad_.vertex[2].tx = x2 ;
    quad_.vertex[2].ty = y2 ;
    quad_.vertex[3].tx = x1 ;
    quad_.vertex[3].ty = y2 ;
    set_texture_rect(rect);
  }

}// namespace graphics
}// namespace xge